//
// Created by DELL on 2023/9/13.
//
#include <iostream>
#include <thread>
#include <future>
#include <string>
#include <chrono>

struct DataType
{
    int n{};
};

int main()
{
    {
        std::cout << "------------- future -----------------\n";
        std::future<DataType> future;
        std::cout << "future is Valid:" << future.valid()  << std::endl;
    }

    {
        std::cout << "------------- std::async -----------------\n";
        auto future = std::async([]{
            return DataType{5};
        });
        std::cout <<"future is Valid:" << future.valid() << " , async Result:" << future.get().n << std::endl;
    }

    {
        std::cout << "------------- promise -----------------\n";
        std::promise<DataType> promise;
        promise.set_value({5});
        // promise.set_value({6}); //set_value只能调用一次，再次调用会抛出异常
        auto future = promise.get_future();
        // auto future2 = promise.get_future(); //get_future只能调用一次，再次调用会抛出异常
        std::cout <<"future is Valid:" << future.valid() << " , async Result:" << future.get().n << std::endl;
    }
    {
        std::cout << "------------- promise exception -----------------\n";
        std::promise<DataType> promise;

//        std::runtime_error error{" custom runtime error"};
//        promise.set_exception(std::make_exception_ptr(error));

        try {
            throw std::runtime_error("error");
        } catch (...) {
            // 如果调用了 promise.set_value ，则不能调用 promise.set_exception ，
            // 否则 promise.set_exception 会抛出异常
            promise.set_exception(std::current_exception());
        }
        auto future = promise.get_future();
        try {
            auto data =  future.get();
            std::cout <<"future is Valid:" << future.valid() << " , async Result:" << data.n << std::endl;
        } catch (const std::exception& e) {
            std::cout << e.what() << std::endl;
        }
    }

    {
        std::cout << "------------- packaged -----------------\n";
        std::packaged_task<DataType(int)> task([](int a) {
            return DataType{a};
        });
        auto future = task.get_future();
        // auto future2 = task.get_future(); //get_future只能调用一次，再次调用会抛出异常
        task(5);
        std::cout <<"future is Valid:" << future.valid()
                  << " , async Result:" << future.get().n << std::endl;
    }

    {
        std::cout << "------------- std::shared_future -----------------\n";

        std::promise<DataType> promise;
        auto future = promise.get_future();
        auto shadedFuture = future.share();
        std::cout << "future is valid: " << future.valid() << std::endl;

        std::thread threads[4];
        for (int i = 0; i < 4; ++i)
        {
            threads[i] = std::thread([future=shadedFuture](int i){
                std::cout << std::to_string(i) + ", future is Valid:" + std::to_string(future.valid())
                                 + " , async Result:" + std::to_string(future.get().n) + "\n";
                future.get(); // shared_future可以多次调用get函数
            }, i);
        }

        std::this_thread::sleep_for(std::chrono::milliseconds{100});
        promise.set_value({5});

        for (int i = 0; i < 4; ++i)
        {
            threads[i].join();
        }
        std::cout << std::endl;
    }

    return 0;
}